﻿using System;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using SovaDataService;
using SovaDataService.SoDataServices;
using SovaDataService.SoModels;
using SovaDataService.SovaDataServices;

namespace SovaWebService
{
    public class Startup
    {
        public IConfiguration Configuration { get; }
        
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        
        // This method gets called by the runtime. Use this method to add services to the container.
        // @see https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();

            services.AddMvc().AddJsonOptions(options =>
            {
                // Added due to exception complaining about self referential loop.
                // Mitigated as pr. https://stackoverflow.com/questions/34753498/self-referencing-loop-detected-in-asp-net-core 
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            });
            services.AddSingleton(new QuestionDataService());
            services.AddSingleton(new AnswerDataService());
            services.AddSingleton(new AuthorDataService());
            services.AddSingleton(new CommentDataService());
            services.AddSingleton(new AccountDataService());
            services.AddSingleton(new MarkedQuestionDataService());
            services.AddSingleton(new SearchDataService());
            services.AddSingleton(new WeightedWordDataService());
            
            var key = Encoding.UTF8.GetBytes(Configuration["security:key"]);
            
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(option =>
                {
                    option.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = false,
                        ValidateIssuer = false,
                        ValidateIssuerSigningKey = true,
                        ValidateLifetime = true,
                        IssuerSigningKey = new SymmetricSecurityKey(key),
                        ClockSkew = TimeSpan.Zero
                    };
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors(builder =>
                builder.WithOrigins("https://localhost:5000")
                    .WithHeaders(new string[]{"Content-Type", "Authorization"})
                    .WithMethods(new string[]{"GET", "POST", "DELETE", "OPTIONS"})
                    .AllowCredentials());
            
            app.UseAuthentication();

            app.UseMvc();

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello Earth!");
            });
        }
    }
}
